package com.test;

import com.test.model.Person;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

public class LambdaStreamPerson {


    static  List<Person> personList = new ArrayList<Person>();
    static {

        personList.add(new Person("Tom", 8900, 23,"male", "New York"));
        personList.add(new Person("Jack", 7000, 25,"male", "Washington"));
        personList.add(new Person("Lily", 7800, 21,"female", "Washington"));
        personList.add(new Person("Anni", 8200, 24,"female", "New York"));
        personList.add(new Person("Owen", 9500, 25,"male", "New York"));
        personList.add(new Person("Alisa", 7900, 26,"female", "New York"));
    }

    @Test
    public void streamTest(){
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
        //（foreach/find/match）
        // // 遍历输出符合条件的元素
        list.stream().filter(x ->x>7).forEach(System.out::println);
        System.out.println("***************************");
        // 匹配第一个
        Optional<Integer> findFirst = list.stream().filter(x -> x > 7).findFirst();

        // 匹配任意（适用于并行流）
        Optional<Integer> findAny = list.parallelStream().filter(x -> x > 7).findAny();

        // 是否包含符合特定条件的元素
        boolean anyMatch = list.stream().anyMatch(x -> x > 6);

        System.out.println("匹配第一个值：" + findFirst.get());
        System.out.println("匹配任意一个值：" + findAny.get());
        System.out.println("是否存在大于6的值：" + anyMatch);
        //筛选（filter）
        // 二 筛选员工中工资高于8000的人，并形成新的集合。 形成新集合依赖collect（收集），后文有详细介绍。
        System.out.println("****** 二*********************");
        List<String> collect = personList.stream().filter(person -> person.getSalary() > 8000).map(Person::getName).collect(Collectors.toList());
        System.out.println("高于8000的员工姓名：" + collect);

        //聚合（max/min/count)
        //案例一：获取String集合中最长的元素。
        List<String> listString = Arrays.asList("adnm", "admmt", "pot", "xbangd", "weoujgsd");
        String s12 = listString.stream().max(Comparator.comparing(x -> x.length())).get();
        String s = listString.stream().max(Comparator.comparing(String::length)).get();

        System.out.println("获取String集合中最长的元素" + s);

    }

    //案例二：获取Integer集合中的最大值。
    @Test
    public  void streamTest1(){
        List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 6);
        Integer integer = list.stream().max(Integer::compareTo).get();
        System.out.println(integer);
        System.out.println("******************************");
        Integer integer1 = list.stream().max(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        }).get();
        System.out.println(integer1);
    }
    //案例三：获取员工工资最高的人。
    @Test
    public void getPersonMaxSalary(){
        Person person = personList.stream().max(Comparator.comparingInt(Person::getSalary)).get();
        System.out.println(person.getSalary());
    }
   //案例四：计算Integer集合中大于6的元素的个数。

    @Test
    public void test1(){
        List<Integer> list = Arrays.asList(7, 6, 4, 8, 2, 11, 9);
        long count = list.stream().filter(x -> x > 6).count();
        System.out.println(" Integer集合中大于6的元素的个数 "+count);
    }
    // 映射(map/flatMap)
    /**
     * map：接收一个函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新的元素。
     * flatMap：接收一个函数作为参数，将流中的每个值都换成另一个流，然后把所有流连接成一个流。
     */
    //案例一：英文字符串数组的元素全部改为大写。整数数组每个元素+3。
    @Test
    public void test2(){
        String[] strArr = { "abcd", "bcdd", "defde", "fTr" };
        List<String> collect = Arrays.asList(strArr).stream().map(String::toUpperCase).collect(Collectors.toList());
        System.out.println("collect " + collect);

        //
        List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);
        List<Integer> integers = intList.stream().map(x -> x + 3).collect(Collectors.toList());
        System.out.println("intList "+integers);
    }
    //将员工的薪资全部增加1000。
    @Test
    public void test3(){
        List<Person> collect = personList.stream().map(person -> {
            person.setSalary(person.getSalary() + 1000);
            return person;
        }).collect(Collectors.toList());
        System.out.println(collect);
    }
    //案例三：将两个字符数组合并成一个新的字符数组。
    @Test
    public void test4(){
        List<String> list = Arrays.asList("m,k,l,a", "1,3,5,7");
        List<String> strings = list.stream().flatMap(s -> {
            String[] split = s.split(",");
            return Arrays.stream(split);
        }).collect(Collectors.toList());
        System.out.println("strings s" + strings);
    }
    //3.5 归约(reduce)
    //案例一：求Integer集合的元素之和、乘积和最大值。
    @Test
    public void test5(){
        List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);
        //// 求和方式1
        Integer integer = list.stream().reduce((x, y) -> x + y).get();
        // 求和方式2
        Integer integer1 = list.stream().reduce(Integer::sum).get();
        // 求和方式3
        Integer integer2 = list.stream().reduce(0, Integer::sum);
        System.out.println("integer " + integer +", " + "integer1 " + integer1 +" integer2 " + integer2);
        //求乘积
        Integer integer3 = list.stream().reduce((x, y) -> x * y).get();
        System.out.println(" integer3 " + integer3);
        // 求最大值方式1
        Integer integer4 = list.stream().reduce((x, y) -> x > y ? x : y).get();
        System.out.println(" integer4 " + integer4);
        // 求最大值方式2
        Integer integer5 = list.stream().reduce(Integer::max).get();
        System.out.println(" integer5 " + integer5);
    }
    @Test
    public void test6(){
        List<String> list = Arrays.asList("AA","BB","CC","DD","EE","FF","GG");
        boolean b = list.stream().anyMatch(x -> x.equals("BB") || x.equals("CC"));
        System.out.println(b);
        //案例二：求所有员工的工资之和和最高工资。
        //1
        Integer integer = personList.stream().map(Person::getSalary).reduce(Integer::sum).get();
        //2
        Integer reduce = personList.stream().map(Person::getSalary).reduce(0, (sum, p) -> sum + p);
        System.out.println(" 员工的工资之和 : "+ integer);
        System.out.println(" 员工的工资之和 : " +reduce);

        //求工资和年龄的总和
        Integer reduce1 = personList.stream().map(x -> x.getSalary() + x.getAge()).reduce(0, (sum, p) -> sum + p);
         //求年龄的和
        Integer reduce2 = personList.stream().reduce(0, (sum, p) -> sum += p.getAge(), Integer::sum);
       System.out.println("员工的工资和年龄的总和 : "+ reduce1);
        System.out.println("员年龄的总和 : "+ reduce2);
        System.out.println("员工的工资和年龄的总和-  员工的工资之和 ： "  + (reduce1- reduce));
        //// 求最高工资方式1：
        Integer integer1 = personList.stream().map(Person::getSalary).reduce(Integer::max).get();
        Integer maxSalary = personList.stream().reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(),
                Integer::max);

        System.out.println("最高工资 integer1 " + integer1);
        System.out.println("最高工资 maxSalary " + maxSalary);
    }
//3.6 收集(collect)
    @Test
    public void test7(){
        //3.6.1 归集(toList/toSet/toMap)
        List<Integer> list = Arrays.asList(1, 6, 3, 4, 6, 7, 9, 6, 20);
        List<Integer> collect = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
        System.out.println(collect);
        Set<Integer> collect1 = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());
        System.out.println(collect1);

        Map<String, Person> collect2 = personList.stream().filter(person -> person.getSalary() > 8000).collect(Collectors.toMap(Person::getName, person -> person));
        System.out.println(collect2);
    }

    //
}
